home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / misc / o-z / x-windows / mesa-amiwin / src / readpix.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-30  |  22.9 KB  |  908 lines

  1. /* readpix.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Id: readpix.c,v 1.10 1995/10/14 16:27:03 brianp Exp $
  26.  
  27. $Log: readpix.c,v $
  28.  * Revision 1.10  1995/10/14  16:27:03  brianp
  29.  * use DD.set_buffer
  30.  *
  31.  * Revision 1.9  1995/10/04  22:08:52  brianp
  32.  * replaced i with j in byte swap function calls
  33.  *
  34.  * Revision 1.8  1995/08/31  21:26:39  brianp
  35.  * use DD.read_*_span instead of dd_read_*_span
  36.  *
  37.  * Revision 1.7  1995/07/24  20:34:16  brianp
  38.  * replaced memset() with MEMSET() and memcpy() with MEMCPY()
  39.  *
  40.  * Revision 1.6  1995/06/12  15:52:41  brianp
  41.  * renamed from readpixels.c to readpix.c
  42.  *
  43.  * Revision 1.5  1995/06/12  15:42:37  brianp
  44.  * changed color arrays to GLubyte
  45.  *
  46.  * Revision 1.4  1995/05/22  21:02:41  brianp
  47.  * Release 1.2
  48.  *
  49.  * Revision 1.3  1995/03/13  20:54:53  brianp
  50.  * added read buffer logic
  51.  *
  52.  * Revision 1.2  1995/03/04  19:29:44  brianp
  53.  * 1.1 beta revision
  54.  *
  55.  * Revision 1.1  1995/02/24  14:27:03  brianp
  56.  * Initial revision
  57.  *
  58.  */
  59.  
  60.  
  61. #include <math.h>
  62. #include <stdlib.h>
  63. #include <string.h>
  64. #include "context.h"
  65. #include "depth.h"
  66. #include "dd.h"
  67. #include "feedback.h"
  68. #include "list.h"
  69. #include "macros.h"
  70. #include "span.h"
  71. #include "stencil.h"
  72.  
  73.  
  74.  
  75.  
  76. /*
  77.  * Compute ceiling of integer quotient of A divided by B:
  78.  */
  79. #define CEILING( A, B )  ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
  80.  
  81.  
  82.  
  83. /*
  84.  * Flip the order of the 4 bytes in each word in the given array.
  85.  */
  86. static void swap4( GLuint *p, GLuint n )
  87. {
  88.    register GLuint i, a, b;
  89.  
  90.    for (i=0;i<n;i++) {
  91.       b = p[i];
  92.       a =  (b >> 24)
  93.     | ((b >> 8) & 0xff00)
  94.     | ((b << 8) & 0xff0000)
  95.     | ((b << 24) & 0xff000000);
  96.       p[i] = a;
  97.    }
  98. }
  99.  
  100.  
  101. /*
  102.  * Flip the order of the 2 bytes in each word in the given array.
  103.  */
  104. static void swap2( GLushort *p, GLuint n )
  105. {
  106.    register GLuint i;
  107.  
  108.    for (i=0;i<n;i++) {
  109.       p[i] = (p[i] >> 8) | ((p[i] << 8) & 0xff00);
  110.    }
  111. }
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118. /**********************************************************************/
  119. /*****                         glReadPixels                       *****/
  120. /**********************************************************************/
  121.  
  122.  
  123. /*
  124.  * Read a block of color index pixels.
  125.  */
  126. static void read_index_pixels( GLint x, GLint y,
  127.                    GLsizei width, GLsizei height,
  128.                    GLenum type, GLvoid *pixels )
  129. {
  130.    GLint i, j;
  131.    GLuint a, s, k, l, start;
  132.  
  133.    /* error checking */
  134.    if (CC.RGBAflag) {
  135.       gl_error( GL_INVALID_OPERATION, "glReadPixels" );
  136.       return;
  137.    }
  138.  
  139.    /* Size of each component */
  140.    switch (type) {
  141.       case GL_UNSIGNED_BYTE:    s = sizeof(GLubyte);    break;
  142.       case GL_BYTE:        s = sizeof(GLbyte);    break;
  143.       case GL_UNSIGNED_SHORT:    s = sizeof(GLushort);    break;
  144.       case GL_SHORT:        s = sizeof(GLshort);    break;
  145.       case GL_UNSIGNED_INT:    s = sizeof(GLuint);    break;
  146.       case GL_INT:        s = sizeof(GLint);    break;
  147.       case GL_FLOAT:        s = sizeof(GLfloat);    break;
  148.       default:
  149.      gl_error( GL_INVALID_ENUM, "glReadPixels(type)" );
  150.      return;
  151.    }
  152.  
  153.    /* Compute packing parameters */
  154.    a = CC.PackAlignment;
  155.    if (CC.PackRowLength>0) {
  156.       l = CC.PackRowLength;
  157.    }
  158.    else {
  159.       l = width;
  160.    }
  161.    /* k = offset between rows in components */
  162.    if (s>=a) {
  163.       k = l;
  164.    }
  165.    else {
  166.       k = a/s * CEILING( s*l, a );
  167.    }
  168.  
  169.    /* offset to first component returned */
  170.    start = CC.PackSkipRows * k + CC.PackSkipPixels;
  171.  
  172.    /* process image row by row */
  173.    for (j=0;j<height;j++,y++) {
  174.       GLuint index[MAX_WIDTH];
  175.       (*DD.read_index_span)( width, x, y, index );
  176.  
  177.       if (CC.Pixel.IndexShift!=0 || CC.Pixel.IndexOffset!=0) {
  178.      GLuint s;
  179.      if (CC.Pixel.IndexShift<0) {
  180.         /* right shift */
  181.         s = -CC.Pixel.IndexShift;
  182.         for (i=0;i<width;i++) {
  183.            index[i] = (index[i] >> s) + CC.Pixel.IndexOffset;
  184.         }
  185.      }
  186.      else {
  187.         /* left shift */
  188.         s = CC.Pixel.IndexShift;
  189.         for (i=0;i<width;i++) {
  190.            index[i] = (index[i] << s) + CC.Pixel.IndexOffset;
  191.         }
  192.      }
  193.       }
  194.  
  195.       if (CC.Pixel.MapColorFlag) {
  196.      for (i=0;i<width;i++) {
  197.         index[i] = CC.Pixel.MapItoI[ index[i] ];
  198.      }
  199.       }
  200.  
  201.       switch (type) {
  202.      case GL_UNSIGNED_BYTE:
  203.         {
  204.            GLubyte *dst = (GLubyte *) pixels + start + j * k;
  205.            for (i=0;i<width;i++) {
  206.           *dst++ = (GLubyte) index[i];
  207.            }
  208.         }
  209.         break;
  210.      case GL_BYTE:
  211.         {
  212.            GLbyte *dst = (GLbyte *) pixels + start + j * k;
  213.            for (i=0;i<width;i++) {
  214.           *dst++ = (GLbyte) index[i];
  215.            }
  216.         }
  217.         break;
  218.      case GL_UNSIGNED_SHORT:
  219.         {
  220.            GLushort *dst = (GLushort *) pixels + start + j * k;
  221.            for (i=0;i<width;i++) {
  222.           *dst++ = (GLushort) index[i];
  223.            }
  224.            if (CC.PackSwapBytes) {
  225.           swap2( (GLushort *) pixels + start + j * k, width );
  226.            }
  227.         }
  228.         break;
  229.      case GL_SHORT:
  230.         {
  231.            GLshort *dst = (GLshort *) pixels + start + j * k;
  232.            for (i=0;i<width;i++) {
  233.           *dst++ = (GLshort) index[i];
  234.            }
  235.            if (CC.PackSwapBytes) {
  236.           swap2( (GLushort *) pixels + start + j * k, width );
  237.            }
  238.         }
  239.         break;
  240.      case GL_UNSIGNED_INT:
  241.         {
  242.            GLuint *dst = (GLuint *) pixels + start + j * k;
  243.            for (i=0;i<width;i++) {
  244.           *dst++ = (GLuint) index[i];
  245.            }
  246.            if (CC.PackSwapBytes) {
  247.           swap4( (GLuint *) pixels + start + j * k, width );
  248.            }
  249.         }
  250.         break;
  251.      case GL_INT:
  252.         {
  253.            GLint *dst = (GLint *) pixels + start + j * k;
  254.            for (i=0;i<width;i++) {
  255.           *dst++ = (GLint) index[i];
  256.            }
  257.            if (CC.PackSwapBytes) {
  258.           swap4( (GLuint *) pixels + start + j * k, width );
  259.            }
  260.         }
  261.         break;
  262.      case GL_FLOAT:
  263.         {
  264.            GLfloat *dst = (GLfloat *) pixels + start + j * k;
  265.            for (i=0;i<width;i++) {
  266.           *dst++ = (GLfloat) index[i];
  267.            }
  268.            if (CC.PackSwapBytes) {
  269.           swap4( (GLuint *) pixels + start + j * k, width );
  270.            }
  271.         }
  272.         break;
  273.       }
  274.  
  275.    }
  276. }
  277.  
  278.  
  279.  
  280. static void read_depth_pixels( GLint x, GLint y,
  281.                    GLsizei width, GLsizei height,
  282.                    GLenum type, GLvoid *pixels )
  283. {
  284.    GLint i, j;
  285.    GLuint a, s, k, l, start;
  286.    GLboolean bias_or_scale;
  287.  
  288.    /* Error checking */
  289.    if (!CC.DepthBuffer) {
  290.       gl_error( GL_INVALID_OPERATION, "glReadPixels" );
  291.       return;
  292.    }
  293.  
  294.    bias_or_scale = CC.Pixel.DepthBias!=0.0 || CC.Pixel.DepthScale!=1.0;
  295.  
  296.    /* Size of each component */
  297.    switch (type) {
  298.       case GL_UNSIGNED_BYTE:    s = sizeof(GLubyte);    break;
  299.       case GL_BYTE:        s = sizeof(GLbyte);    break;
  300.       case GL_UNSIGNED_SHORT:    s = sizeof(GLushort);    break;
  301.       case GL_SHORT:        s = sizeof(GLshort);    break;
  302.       case GL_UNSIGNED_INT:    s = sizeof(GLuint);    break;
  303.       case GL_INT:        s = sizeof(GLint);    break;
  304.       case GL_FLOAT:        s = sizeof(GLfloat);    break;
  305.       default:
  306.      gl_error( GL_INVALID_ENUM, "glReadPixels(type)" );
  307.      return;
  308.    }
  309.  
  310.    /* Compute packing parameters */
  311.    a = CC.PackAlignment;
  312.    if (CC.PackRowLength>0) {
  313.       l = CC.PackRowLength;
  314.    }
  315.    else {
  316.       l = width;
  317.    }
  318.    /* k = offset between rows in components */
  319.    if (s>=a) {
  320.       k = l;
  321.    }
  322.    else {
  323.       k = a/s * CEILING( s*l, a );
  324.    }
  325.  
  326.    /* offset to first component returned */
  327.    start = CC.PackSkipRows * k + CC.PackSkipPixels;
  328.  
  329.    /* process image row by row */
  330.    for (j=0;j<height;j++,y++) {
  331.       GLfloat depth[MAX_WIDTH];
  332.  
  333.       gl_read_depth_span( width, x, y, depth );
  334.  
  335.       if (bias_or_scale) {
  336.      for (i=0;i<width;i++) {
  337.         GLfloat d;
  338.         d = depth[i] * CC.Pixel.DepthScale + CC.Pixel.DepthBias;
  339.         depth[i] = CLAMP( d, 0.0, 1.0 );
  340.      }
  341.       }
  342.  
  343.       switch (type) {
  344.      case GL_UNSIGNED_BYTE:
  345.          {
  346.            GLubyte *dst = (GLubyte *) pixels + start + j * k;
  347.            for (i=0;i<width;i++) {
  348.           *dst++ = FLOAT_TO_UBYTE( depth[i] );
  349.            }
  350.         }
  351.         break;
  352.      case GL_BYTE:
  353.          {
  354.            GLbyte *dst = (GLbyte *) pixels + start + j * k;
  355.            for (i=0;i<width;i++) {
  356.           *dst++ = FLOAT_TO_BYTE( depth[i] );
  357.            }
  358.         }
  359.         break;
  360.      case GL_UNSIGNED_SHORT:
  361.          {
  362.            GLushort *dst = (GLushort *) pixels + start + j * k;
  363.            for (i=0;i<width;i++) {
  364.           *dst++ = FLOAT_TO_USHORT( depth[i] );
  365.            }
  366.            if (CC.PackSwapBytes) {
  367.           swap2( (GLushort *) pixels + start + j * k, width );
  368.            }
  369.         }
  370.         break;
  371.      case GL_SHORT:
  372.          {
  373.            GLshort *dst = (GLshort *) pixels + start + j * k;
  374.            for (i=0;i<width;i++) {
  375.           *dst++ = FLOAT_TO_SHORT( depth[i] );
  376.            }
  377.            if (CC.PackSwapBytes) {
  378.           swap2( (GLushort *) pixels + start + j * k, width );
  379.            }
  380.         }
  381.         break;
  382.      case GL_UNSIGNED_INT:
  383.          {
  384.            GLuint *dst = (GLuint *) pixels + start + j * k;
  385.            for (i=0;i<width;i++) {
  386.           *dst++ = FLOAT_TO_UINT( depth[i] );
  387.            }
  388.            if (CC.PackSwapBytes) {
  389.           swap4( (GLuint *) pixels + start + j * k, width );
  390.            }
  391.         }
  392.         break;
  393.      case GL_INT:
  394.          {
  395.            GLint *dst = (GLint *) pixels + start + j * k;
  396.            for (i=0;i<width;i++) {
  397.           *dst++ = FLOAT_TO_INT( depth[i] );
  398.            }
  399.            if (CC.PackSwapBytes) {
  400.           swap4( (GLuint *) pixels + start + j * k, width );
  401.            }
  402.         }
  403.         break;
  404.      case GL_FLOAT:
  405.          {
  406.            GLfloat *dst = (GLfloat *) pixels + start + j * k;
  407.            for (i=0;i<width;i++) {
  408.           *dst++ = depth[i];
  409.            }
  410.            if (CC.PackSwapBytes) {
  411.           swap4( (GLuint *) pixels + start + j * k, width );
  412.            }
  413.         }
  414.         break;
  415.       }
  416.  
  417.    }
  418. }
  419.  
  420.  
  421.  
  422.  
  423. static void read_stencil_pixels( GLint x, GLint y,
  424.                  GLsizei width, GLsizei height,
  425.                  GLenum type, GLvoid *pixels )
  426. {
  427.    GLint i, j;
  428.    GLuint a, s, k, l, start;
  429.    GLboolean shift_or_offset;
  430.  
  431.    if (!CC.StencilBuffer) {
  432.       gl_error( GL_INVALID_OPERATION, "glReadPixels" );
  433.       return;
  434.    }
  435.  
  436.    shift_or_offset = CC.Pixel.IndexShift!=0 || CC.Pixel.IndexOffset!=0;
  437.  
  438.    /* Size of each component */
  439.    switch (type) {
  440.       case GL_UNSIGNED_BYTE:    s = sizeof(GLubyte);    break;
  441.       case GL_BYTE:        s = sizeof(GLbyte);    break;
  442.       case GL_UNSIGNED_SHORT:    s = sizeof(GLushort);    break;
  443.       case GL_SHORT:        s = sizeof(GLshort);    break;
  444.       case GL_UNSIGNED_INT:    s = sizeof(GLuint);    break;
  445.       case GL_INT:        s = sizeof(GLint);    break;
  446.       case GL_FLOAT:        s = sizeof(GLfloat);    break;
  447.       default:
  448.      gl_error( GL_INVALID_ENUM, "glReadPixels(type)" );
  449.      return;
  450.    }
  451.  
  452.    /* Compute packing parameters */
  453.    a = CC.PackAlignment;
  454.    if (CC.PackRowLength>0) {
  455.       l = CC.PackRowLength;
  456.    }
  457.    else {
  458.       l = width;
  459.    }
  460.    /* k = offset between rows in components */
  461.    if (s>=a) {
  462.       k = l;
  463.    }
  464.    else {
  465.       k = a/s * CEILING( s*l, a );
  466.    }
  467.  
  468.    /* offset to first component returned */
  469.    start = CC.PackSkipRows * k + CC.PackSkipPixels;
  470.  
  471.    /* process image row by row */
  472.    for (j=0;j<height;j++,y++) {
  473.       GLubyte stencil[MAX_WIDTH];
  474.  
  475.       gl_read_stencil_span( width, x, y, stencil );
  476.  
  477.       if (shift_or_offset) {
  478.      GLuint s;
  479.      if (CC.Pixel.IndexShift<0) {
  480.         /* right shift */
  481.         s = -CC.Pixel.IndexShift;
  482.         for (i=0;i<width;i++) {
  483.            stencil[i] = (stencil[i] >> s) + CC.Pixel.IndexOffset;
  484.         }
  485.      }
  486.      else {
  487.         /* left shift */
  488.         s = CC.Pixel.IndexShift;
  489.         for (i=0;i<width;i++) {
  490.            stencil[i] = (stencil[i] << s) + CC.Pixel.IndexOffset;
  491.         }
  492.      }
  493.       }
  494.  
  495.       if (CC.Pixel.MapStencilFlag) {
  496.      for (i=0;i<width;i++) {
  497.         stencil[i] = CC.Pixel.MapStoS[ stencil[i] ];
  498.      }
  499.       }
  500.  
  501.       switch (type) {
  502.      case GL_UNSIGNED_BYTE:
  503.         {
  504.            GLubyte *dst = (GLubyte *) pixels + start + j * k;
  505.            MEMCPY( dst, stencil, width );
  506.         }
  507.         break;
  508.      case GL_BYTE:
  509.         {
  510.            GLbyte *dst = (GLbyte  *) pixels + start + j * k;
  511.            MEMCPY( dst, stencil, width );
  512.         }
  513.         break;
  514.      case GL_UNSIGNED_SHORT:
  515.         {
  516.            GLushort *dst = (GLushort *) pixels + start + j * k;
  517.            for (i=0;i<width;i++) {
  518.           *dst++ = (GLushort) stencil[i];
  519.            }
  520.            if (CC.PackSwapBytes) {
  521.           swap2( (GLushort *) pixels + start +j * k, width );
  522.            }
  523.         }
  524.         break;
  525.      case GL_SHORT:
  526.         {
  527.            GLshort *dst = (GLshort *) pixels + start + j * k;
  528.            for (i=0;i<width;i++) {
  529.           *dst++ = (GLshort) stencil[i];
  530.            }
  531.            if (CC.PackSwapBytes) {
  532.           swap2( (GLushort *) pixels + start +j * k, width );
  533.            }
  534.         }
  535.         break;
  536.      case GL_UNSIGNED_INT:
  537.         {
  538.            GLuint *dst = (GLuint *) pixels + start + j * k;
  539.            for (i=0;i<width;i++) {
  540.           *dst++ = (GLuint) stencil[i];
  541.            }
  542.            if (CC.PackSwapBytes) {
  543.           swap4( (GLuint *) pixels + start +j * k, width );
  544.            }
  545.         }
  546.         break;
  547.      case GL_INT:
  548.         {
  549.            GLint *dst = (GLint *) pixels + start + j * k;
  550.            for (i=0;i<width;i++) {
  551.           *dst++ = (GLint) stencil[i];
  552.            }
  553.            if (CC.PackSwapBytes) {
  554.           swap4( (GLuint *) pixels + start +j * k, width );
  555.            }
  556.         }
  557.         break;
  558.      case GL_FLOAT:
  559.         {
  560.            GLfloat *dst = (GLfloat *) pixels + start + j * k;
  561.            for (i=0;i<width;i++) {
  562.           *dst++ = (GLfloat) stencil[i];
  563.            }
  564.            if (CC.PackSwapBytes) {
  565.           swap4( (GLuint *) pixels + start +j * k, width );
  566.            }
  567.         }
  568.         break;
  569.       }
  570.  
  571.    }
  572. }
  573.  
  574.  
  575.  
  576. /*
  577.  * Test if scaling or biasing of colors is needed.
  578.  */
  579. static GLboolean scale_or_bias_rgba( void )
  580. {
  581.    if (CC.Pixel.RedScale!=1.0F   || CC.Pixel.RedBias!=0.0F ||
  582.        CC.Pixel.GreenScale!=1.0F || CC.Pixel.GreenBias!=0.0F ||
  583.        CC.Pixel.BlueScale!=1.0F  || CC.Pixel.BlueBias!=0.0F ||
  584.        CC.Pixel.AlphaScale!=1.0F || CC.Pixel.AlphaBias!=0.0F) {
  585.       return GL_TRUE;
  586.    }
  587.    else {
  588.       return GL_FALSE;
  589.    }
  590. }
  591.  
  592.  
  593.  
  594. /*
  595.  * Apply scale and bias factors to an array of RGBA pixels.
  596.  */
  597. static void scale_and_bias_rgba( GLint n,
  598.                  GLfloat red[], GLfloat green[],
  599.                  GLfloat blue[], GLfloat alpha[] )
  600. {
  601.    register GLint i;
  602.    register GLfloat r, g, b, a;
  603.  
  604.    for (i=0;i<n;i++) {
  605.       r = red[i]   * CC.Pixel.RedScale   + CC.Pixel.RedBias;
  606.       g = green[i] * CC.Pixel.GreenScale + CC.Pixel.GreenBias;
  607.       b = blue[i]  * CC.Pixel.BlueScale  + CC.Pixel.BlueBias;
  608.       a = alpha[i] * CC.Pixel.AlphaScale + CC.Pixel.AlphaBias;
  609.       red[i]   = CLAMP( r, 0.0F, 1.0F );
  610.       green[i] = CLAMP( g, 0.0F, 1.0F );
  611.       blue[i]  = CLAMP( b, 0.0F, 1.0F );
  612.       alpha[i] = CLAMP( a, 0.0F, 1.0F );
  613.    }
  614. }
  615.  
  616.  
  617.  
  618. /*
  619.  * Apply pixel mapping to an array of RGBA pixels.
  620.  */
  621. static void map_rgba( GLint n,
  622.               GLfloat red[], GLfloat green[],
  623.               GLfloat blue[], GLfloat alpha[] )
  624. {
  625.    register GLint i;
  626.    register GLint ir, ig, ib, ia;
  627.  
  628.    for (i=0;i<n;i++) {
  629.       ir = (GLint) (red[i]   * CC.Pixel.MapRtoRsize);
  630.       ig = (GLint) (green[i] * CC.Pixel.MapGtoGsize);
  631.       ib = (GLint) (blue[i]  * CC.Pixel.MapBtoBsize);
  632.       ia = (GLint) (alpha[i] * CC.Pixel.MapAtoAsize);
  633.       red[i]   = CC.Pixel.MapRtoR[ir];
  634.       green[i] = CC.Pixel.MapGtoG[ig];
  635.       blue[i]  = CC.Pixel.MapBtoB[ib];
  636.       alpha[i] = CC.Pixel.MapAtoA[ia];
  637.    }
  638. }
  639.  
  640.  
  641.  
  642.  
  643. /*
  644.  * Read R, G, B, A, RGB, L, or LA pixels.
  645.  */
  646. static void read_color_pixels( GLint x, GLint y,
  647.                    GLsizei width, GLsizei height,
  648.                    GLenum format, GLenum type, GLvoid *pixels )
  649. {
  650.    GLint i, j, n, a, s, l, k;
  651.    GLboolean scale_or_bias;
  652.    GLfloat red[MAX_WIDTH], green[MAX_WIDTH], blue[MAX_WIDTH], alpha[MAX_WIDTH];
  653.    GLboolean r_flag, g_flag, b_flag, a_flag, l_flag;
  654.    GLuint start;
  655.  
  656.    scale_or_bias = scale_or_bias_rgba();
  657.  
  658.    /* Determine how many / which components to return */
  659.    r_flag = g_flag = b_flag = a_flag = l_flag = GL_FALSE;
  660.    switch (format) {
  661.       case GL_RED:                r_flag = GL_TRUE;  n = 1;  break;
  662.       case GL_GREEN:                g_flag = GL_TRUE;  n = 1;  break;
  663.       case GL_BLUE:                b_flag = GL_TRUE;  n = 1;  break;
  664.       case GL_ALPHA:                a_flag = GL_TRUE;  n = 1;  break;
  665.       case GL_LUMINANCE:            l_flag = GL_TRUE;  n = 1;  break;
  666.       case GL_LUMINANCE_ALPHA:           l_flag = a_flag = GL_TRUE;  n = 2;  break;
  667.       case GL_RGB:          r_flag = g_flag = b_flag = GL_TRUE;  n = 3;  break;
  668.       case GL_RGBA:  r_flag = g_flag = b_flag = a_flag = GL_TRUE;  n = 4;  break;
  669.       default:
  670.      gl_error( GL_INVALID_ENUM, "glReadPixels(format)" );
  671.    }
  672.  
  673.    /* Size of each component */
  674.    switch (type) {
  675.       case GL_UNSIGNED_BYTE:    s = sizeof(GLubyte);    break;
  676.       case GL_BYTE:        s = sizeof(GLbyte);    break;
  677.       case GL_UNSIGNED_SHORT:    s = sizeof(GLushort);    break;
  678.       case GL_SHORT:        s = sizeof(GLshort);    break;
  679.       case GL_UNSIGNED_INT:    s = sizeof(GLuint);    break;
  680.       case GL_INT:        s = sizeof(GLint);    break;
  681.       case GL_FLOAT:        s = sizeof(GLfloat);    break;
  682.       default:
  683.      gl_error( GL_INVALID_ENUM, "glReadPixels(type)" );
  684.      return;
  685.    }
  686.  
  687.    /* Compute packing parameters */
  688.    a = CC.PackAlignment;
  689.    if (CC.PackRowLength>0) {
  690.       l = CC.PackRowLength;
  691.    }
  692.    else {
  693.       l = width;
  694.    }
  695.    /* k = offset between rows in components */
  696.    if (s>=a) {
  697.       k = n * l;
  698.    }
  699.    else {
  700.       k = a/s * CEILING( s*n*l, a );
  701.    }
  702.  
  703.    /* offset to first component returned */
  704.    start = CC.PackSkipRows * k + CC.PackSkipPixels * n;
  705.  
  706.    /* process image row by row */
  707.    for (j=0;j<height;j++,y++) {
  708.  
  709.       /*
  710.        * Read the pixels from frame buffer
  711.        */
  712.       if (CC.RGBAflag) {
  713.      GLubyte r[MAX_WIDTH], g[MAX_WIDTH], b[MAX_WIDTH], a[MAX_WIDTH];
  714.      GLfloat rscale = 1.0F / CC.RedScale;
  715.      GLfloat gscale = 1.0F / CC.GreenScale;
  716.      GLfloat bscale = 1.0F / CC.BlueScale;
  717.      GLfloat ascale = 1.0F / CC.AlphaScale;
  718.  
  719.      /* read colors and convert to floats */
  720.      (*DD.read_color_span)( width, x, y, r, g, b, a );
  721.      for (i=0;i<width;i++) {
  722.         red[i]   = r[i] * rscale;
  723.         green[i] = g[i] * gscale;
  724.         blue[i]  = b[i] * bscale;
  725.         alpha[i] = a[i] * ascale;
  726.      }
  727.  
  728.      if (scale_or_bias) {
  729.         scale_and_bias_rgba( width, red, green, blue, alpha );
  730.      }
  731.      if (CC.Pixel.MapColorFlag) {
  732.         map_rgba( width, red, green, blue, alpha );
  733.      }
  734.       }
  735.       else {
  736.      /* convert CI values to RGBA */
  737.      GLuint index[MAX_WIDTH];
  738.      (*DD.read_index_span)( width, x, y, index );
  739.  
  740.      if (CC.Pixel.IndexShift!=0 || CC.Pixel.IndexOffset!=0) {
  741.         GLuint s;
  742.         if (CC.Pixel.IndexShift<0) {
  743.            /* right shift */
  744.            s = -CC.Pixel.IndexShift;
  745.            for (i=0;i<width;i++) {
  746.           index[i] = (index[i] >> s) + CC.Pixel.IndexOffset;
  747.            }
  748.         }
  749.         else {
  750.            /* left shift */
  751.            s = CC.Pixel.IndexShift;
  752.            for (i=0;i<width;i++) {
  753.           index[i] = (index[i] << s) + CC.Pixel.IndexOffset;
  754.            }
  755.         }
  756.      }
  757.  
  758.      for (i=0;i<width;i++) {
  759.         red[i]   = CC.Pixel.MapItoR[ index[i] ];
  760.         green[i] = CC.Pixel.MapItoG[ index[i] ];
  761.         blue[i]  = CC.Pixel.MapItoB[ index[i] ];
  762.         alpha[i] = CC.Pixel.MapItoA[ index[i] ];
  763.      }
  764.       }
  765.  
  766.       /*
  767.        * Pack/transfer/store the pixels
  768.        */
  769.  
  770.       switch (type) {
  771.      case GL_UNSIGNED_BYTE:
  772.         {
  773.            GLubyte *dst = (GLubyte *) pixels + start + j * k;
  774.            for (i=0;i<width;i++) {
  775.           if (r_flag)  *dst++ = FLOAT_TO_UBYTE( red[i] );
  776.           if (g_flag)  *dst++ = FLOAT_TO_UBYTE( green[i] );
  777.           if (b_flag)  *dst++ = FLOAT_TO_UBYTE( blue[i] );
  778.           if (l_flag)  *dst++ = FLOAT_TO_UBYTE(red[i]+green[i]+blue[i]);
  779.           if (a_flag)  *dst++ = FLOAT_TO_UBYTE( alpha[i] );
  780.            }
  781.         }
  782.         break;
  783.      case GL_BYTE:
  784.         {
  785.            GLbyte *dst = (GLbyte *) pixels + start + j * k;
  786.            for (i=0;i<width;i++) {
  787.           if (r_flag)  *dst++ = FLOAT_TO_BYTE( red[i] );
  788.           if (g_flag)  *dst++ = FLOAT_TO_BYTE( green[i] );
  789.           if (b_flag)  *dst++ = FLOAT_TO_BYTE( blue[i] );
  790.           if (l_flag)  *dst++ = FLOAT_TO_BYTE(red[i]+green[i]+blue[i]);
  791.           if (a_flag)  *dst++ = FLOAT_TO_BYTE( alpha[i] );
  792.            }
  793.         }
  794.         break;
  795.      case GL_UNSIGNED_SHORT:
  796.         {
  797.            GLushort *dst = (GLushort *) pixels + start + j * k;
  798.            for (i=0;i<width;i++) {
  799.           if (r_flag)  *dst++ = FLOAT_TO_USHORT( red[i] );
  800.           if (g_flag)  *dst++ = FLOAT_TO_USHORT( green[i] );
  801.           if (b_flag)  *dst++ = FLOAT_TO_USHORT( blue[i] );
  802.           if (l_flag)  *dst++ = FLOAT_TO_USHORT(red[i]+green[i]+blue[i]);
  803.           if (a_flag)  *dst++ = FLOAT_TO_USHORT( alpha[i] );
  804.            }
  805.         }
  806.         if (CC.PackSwapBytes) {
  807.            swap2( (GLushort *) pixels + start + j * k, width*n );
  808.         }
  809.         break;
  810.      case GL_SHORT:
  811.         {
  812.            GLshort *dst = (GLshort *) pixels + start + j * k;
  813.            for (i=0;i<width;i++) {
  814.           if (r_flag)  *dst++ = FLOAT_TO_SHORT( red[i] );
  815.           if (g_flag)  *dst++ = FLOAT_TO_SHORT( green[i] );
  816.           if (b_flag)  *dst++ = FLOAT_TO_SHORT( blue[i] );
  817.           if (l_flag)  *dst++ = FLOAT_TO_SHORT(red[i]+green[i]+blue[i]);
  818.           if (a_flag)  *dst++ = FLOAT_TO_SHORT( alpha[i] );
  819.            }
  820.            if (CC.PackSwapBytes) {
  821.           swap2( (GLushort *) pixels + start + j * k, width*n );
  822.            }
  823.         }
  824.         break;
  825.      case GL_UNSIGNED_INT:
  826.         {
  827.            GLuint *dst = (GLuint *) pixels + start + j * k;
  828.            for (i=0;i<width;i++) {
  829.           if (r_flag)  *dst++ = FLOAT_TO_UINT( red[i] );
  830.           if (g_flag)  *dst++ = FLOAT_TO_UINT( green[i] );
  831.           if (b_flag)  *dst++ = FLOAT_TO_UINT( blue[i] );
  832.           if (l_flag)  *dst++ = FLOAT_TO_UINT(red[i]+green[i]+blue[i]);
  833.           if (a_flag)  *dst++ = FLOAT_TO_UINT( alpha[i] );
  834.            }
  835.            if (CC.PackSwapBytes) {
  836.           swap4( (GLuint *) pixels + start + j * k, width*n );
  837.            }
  838.         }
  839.         break;
  840.      case GL_INT:
  841.         {
  842.            GLint *dst = (GLint *) pixels + start + j * k;
  843.            for (i=0;i<width;i++) {
  844.           if (r_flag)  *dst++ = FLOAT_TO_INT( red[i] );
  845.           if (g_flag)  *dst++ = FLOAT_TO_INT( green[i] );
  846.           if (b_flag)  *dst++ = FLOAT_TO_INT( blue[i] );
  847.           if (l_flag)  *dst++ = FLOAT_TO_INT(red[i]+green[i]+blue[i]);
  848.           if (a_flag)  *dst++ = FLOAT_TO_INT( alpha[i] );
  849.            }
  850.            if (CC.PackSwapBytes) {
  851.           swap4( (GLuint *) pixels + start + j * k, width*n );
  852.            }
  853.         }
  854.         break;
  855.      case GL_FLOAT:
  856.         {
  857.            GLfloat *dst = (GLfloat *) pixels + start + j * k;
  858.            for (i=0;i<width;i++) {
  859.           if (r_flag)  *dst++ = red[i];
  860.           if (g_flag)  *dst++ = green[i];
  861.           if (b_flag)  *dst++ = blue[i];
  862.           if (l_flag)  *dst++ = red[i]+green[i]+blue[i];
  863.           if (a_flag)  *dst++ = alpha[i];
  864.            }
  865.            if (CC.PackSwapBytes) {
  866.           swap4( (GLuint *) pixels + start + j * k, width*n );
  867.            }
  868.         }
  869.         break;
  870.       }
  871.  
  872.    }
  873. }
  874.  
  875.  
  876.  
  877. void glReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
  878.            GLenum format, GLenum type, GLvoid *pixels )
  879. {
  880.    (void) (*DD.set_buffer)( CC.Pixel.ReadBuffer );
  881.  
  882.    switch (format) {
  883.       case GL_COLOR_INDEX:
  884.          read_index_pixels( x, y, width, height, type, pixels );
  885.      break;
  886.       case GL_STENCIL_INDEX:
  887.      read_stencil_pixels( x, y, width, height, type, pixels );
  888.          break;
  889.       case GL_DEPTH_COMPONENT:
  890.      read_depth_pixels( x, y, width, height, type, pixels );
  891.      break;
  892.       case GL_RED:
  893.       case GL_GREEN:
  894.       case GL_BLUE:
  895.       case GL_ALPHA:
  896.       case GL_RGB:
  897.       case GL_LUMINANCE:
  898.       case GL_LUMINANCE_ALPHA:
  899.       case GL_RGBA:
  900.      read_color_pixels( x, y, width, height, format, type, pixels );
  901.      break;
  902.       default:
  903.      gl_error( GL_INVALID_ENUM, "glReadPixels(format)" );
  904.    }
  905.  
  906.    (void) (*DD.set_buffer)( CC.Color.DrawBuffer );
  907. }
  908.